import axios, {
  AxiosInstance,
  AxiosRequestConfig,
  InternalAxiosRequestConfig,
  AxiosResponse,
  AxiosError,
} from "axios";

/**
 * 自定义的拦截器配置
 */
export interface InterceptorsConfig {
  /** 请求截器 */
  reqHandler?: (
    config: InternalAxiosRequestConfig
  ) => InternalAxiosRequestConfig;
  /** 请求错误拦截器 */
  reqErrHandler?: (error: AxiosError) => any;
  /** 响应成功拦截器 */
  resHandler?: (res: AxiosResponse) => AxiosResponse;
  /** 响应错误拦截器 */
  resErrHandler?: (error: AxiosError) => any;
}

class WebApiKit {
  /** Axios 实例 */
  private http: AxiosInstance;

  /**
   * 创建 HttpRequest 实例
   * @param config Axios 请求配置
   * @param interceptors 拦截器配置
   */
  constructor(initialConfig?: {
    axiosConfig?: AxiosRequestConfig;
    interceptorConfig?: InterceptorsConfig;
  }) {
    // 解构初始化参数
    const { axiosConfig = {}, interceptorConfig = {} } = initialConfig || {};

    // 默认请求头
    axiosConfig.headers ??= {};
    axiosConfig.headers["Content-Type"] ??= "application/json";

    // 创建 Axios 实例
    this.http = axios.create(axiosConfig);

    // 注册请求拦截器
    this.http.interceptors.request.use(
      (config: InternalAxiosRequestConfig) => {
        return interceptorConfig?.reqHandler?.(config) || config;
      },
      (error: AxiosError) => {
        return interceptorConfig?.reqErrHandler?.(error) || error;
      }
    );

    // 注册响应拦截器
    this.http.interceptors.response.use(
      (response: AxiosResponse) => {
        return interceptorConfig?.resHandler?.(response) || response.data;
      },
      (error: AxiosError) => {
        return interceptorConfig?.resErrHandler?.(error) || error;
      }
    );
  }

  /**
   * 发送 GET 请求
   * @param url 请求地址
   * @param config 请求配置
   * @returns 返回 Promise 对象
   */
  public get<T = any>(
    url: string,
    params?: Record<string, any>,
    config?: Omit<AxiosRequestConfig, "params">
  ): Promise<T> {
    return this.http.get(url, { ...config, params });
  }

  /**
   * 发送 POST 请求
   * @param url 请求地址
   * @param data 请求体数据
   * @param params 请求参数
   * @param config 请求配置
   * @returns 返回 Promise 对象
   */
  public post<T = any>(
    url: string,
    data?: any,
    params?: Record<string, any>,
    config?: Omit<AxiosRequestConfig, "params">
  ): Promise<T> {
    return this.http.post(url, data, { ...config, params });
  }

  /**
   * 发送 PUT 请求
   * @param url 请求地址
   * @param data 请求体数据
   * @param params 请求参数
   * @param config 请求配置
   * @returns 返回 Promise 对象
   */
  public put<T = any>(
    url: string,
    data?: any,
    params?: Record<string, any>,
    config?: Omit<AxiosRequestConfig, "params">
  ): Promise<T> {
    return this.http.put(url, data, { ...config, params });
  }

  /**
   * 发送 DELETE 请求
   * @param url 请求地址
   * @param params 请求参数
   * @param config 请求配置
   * @returns 返回 Promise 对象
   */
  public delete<T = any>(
    url: string,
    params?: Record<string, any>,
    config?: Omit<AxiosRequestConfig, "params">
  ): Promise<T> {
    return this.http.delete(url, { ...config, params });
  }

  /**
   * 发送 PATCH 请求
   * @param url 请求地址
   * @param data 请求体数据
   * @param params 请求参数
   * @param config 请求配置
   * @returns 返回 Promise 对象
   */
  public patch<T = any>(
    url: string,
    data?: any,
    params?: Record<string, any>,
    config?: Omit<AxiosRequestConfig, "params">
  ): Promise<T> {
    return this.http.patch(url, data, { ...config, params });
  }
}
export default WebApiKit;
